﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using BusinessPlatformTool.BusinessObjectStructure;
using System.IO;
using System.Text.RegularExpressions;
using BusinessPlatform.Data;
using BusinessPlatformTool.Enumerator;

namespace BusinessPlatformTool.Parser
{
    delegate void ShowErrorMessage(string ErrorMessage);
    internal class DataStructureParser
    {
        public event ShowErrorMessage ShowErrorMessageEvent;
        private IBusinessObject _BO;
        private IDictionary<string, IValidDataType> _DicValidDataType;
        internal DataStructureParser()
        {
        }
        /// <summary>
        /// 添加表
        /// </summary>
        /// <param name="bo"></param>
        /// <param name="xml"></param>
        /// <param name="xpath"></param>
        /// <param name="IsPrimary"></param>
        /// <returns></returns>
        private ITable AddTable(IBusinessObject bo, XmlDocument xml, string xpath, bool IsPrimary)
        {
            var table = bo.Lines.New();
            table.IsPrimary = IsPrimary;
            table.Name = xml.SelectSingleNode(xpath).Attributes["Name"].Value;
            table.Description = xml.SelectSingleNode(xpath).Attributes["Description"].Value;
            string ObjectTypeString = xml.SelectSingleNode(xpath).Attributes["Type"].Value;
            EnumBusinessObjectType ObjectType;
            if (Enum.TryParse<EnumBusinessObjectType>(ObjectTypeString, true, out ObjectType) == false)
            {
                if (ShowErrorMessageEvent != null)
                {
                    ShowErrorMessageEvent("[" + table.Name + "]数据表的业务类型定义错误。");
                    return null;
                }
            }
            table.Type = ObjectType;
            table.ClassName = xml.SelectSingleNode(xpath).Attributes["ClassName"].Value;
            return table;
        }
        private bool AddFeild(ITable table, XmlNode nodefield)
        {
            var field = table.Lines.New();
            field.Name = nodefield.Attributes["Name"].Value;
            field.Description = nodefield.Attributes["Description"].Value;
            string DbTypeString = nodefield.Attributes["DbType"].Value;
            DbType DbType;
            if (Enum.TryParse<DbType>(DbTypeString, true, out DbType) == false)
            {
                if (ShowErrorMessageEvent != null)
                {
                    ShowErrorMessageEvent("[" + field.Name + "]字段类型定义错误。");
                    return false;
                }
            }

            field.DbType = DbType;
            field.PSize = nodefield.Attributes["PSize"].Value;
            field.SSize = nodefield.Attributes["SSize"].Value;
            field.DefaultValue = nodefield.Attributes["DefaultValue"].Value;
            field.PropertyName = nodefield.Attributes["PropertyName"].Value;
            if (nodefield.SelectSingleNode("child::*") != null)
                field.PropertyType = nodefield.SelectSingleNode("child::*").Attributes["name"].Value;
            else
                field.PropertyType = DbType.ToString();
            field.IsPrimaryKey = nodefield.Attributes["IsPrimaryKey"].Value == "Yes" ? true : false;
            field.IsUnionKey = nodefield.Attributes["IsUnionKey"].Value == "Yes" ? true : false;
            field.IsNull = nodefield.Attributes["IsNull"].Value == "Yes" ? true : false;
            #region 控件类型
            BOControlType.WinFormControlType iWinFormControlType;
            switch (field.DbType)
            {
                case Enumerator.DbType.Date:
                case Enumerator.DbType.Datetime:
                case Enumerator.DbType.Datetime2:
                    iWinFormControlType = BOControlType.WinFormControlType.DateTimePicker;
                    break;
                case Enumerator.DbType.Binary:
                case Enumerator.DbType.Bit:
                    iWinFormControlType = BOControlType.WinFormControlType.CheckBox;
                    break;
                case Enumerator.DbType.Char:
                    if (field.PSize == "1")
                        iWinFormControlType = BOControlType.WinFormControlType.CheckBox;
                    else
                        iWinFormControlType = BOControlType.WinFormControlType.TextBox;
                    break;
                default:
                    iWinFormControlType = BOControlType.WinFormControlType.TextBox;
                    break;
            }
            if (field.DbType == Enumerator.DbType.Char && field.PSize != "1")
            {
                if (nodefield.SelectSingleNode("child::*") != null)
                    iWinFormControlType = BOControlType.WinFormControlType.ComboBox;
            }
            field.ControlType = iWinFormControlType;
            #endregion
            return true;
        }
        /// <summary>
        /// 解析XML文件文档到业务对象（BusinessObject）
        /// </summary>
        /// <param name="xml"></param>
        public bool Parser(XmlDocument xml)
        {
            string xpath = string.Empty;
            #region 业务对象
            IBusinessObject bo;
            ITable table;
            #region 对象
            bo = new BusinessObject();
            xpath = "//ObjectStructure";
            foreach (XmlNode node in xml.SelectNodes(xpath))
            {
                #region 对象
                string ObjectTypeString = node.SelectSingleNode("child::*").Attributes["ObjectType"].Value;
                EnumBusinessObjectType ObjectType;
                if (Enum.TryParse<EnumBusinessObjectType>(ObjectTypeString, true, out ObjectType) == false)
                {
                    if (ShowErrorMessageEvent != null)
                    {
                        ShowErrorMessageEvent("数据对象的业务类型定义错误。");
                        return false;
                    }
                }
                bo.ObjectType = ObjectType;
                bo.ObjectCode = node.SelectSingleNode("child::*").Attributes["ObjectCode"].Value;
                bo.ObjectName = node.SelectSingleNode("child::*").Attributes["ObjectName"].Value;
                bo.NameSpace = node.SelectSingleNode("child::*").Attributes["NameSpace"].Value;
                bo.IsLog = node.SelectSingleNode("child::*").Attributes["IsLog"].Value == "Yes" ? true : false;
                #endregion
                #region 主表表
                var xpathc = "//Table[@Name='" + node.SelectSingleNode("child::*").Attributes["TableName"].Value + "']";
                table = AddTable(bo, xml, xpathc, true);
                if (table == null) return false;
                #endregion
                #region 字段
                foreach (XmlNode nodefield in xml.SelectSingleNode(xpathc).SelectNodes("child::*"))
                {
                    if (AddFeild(table, nodefield) == false)
                        return false;
                }
                #endregion
                var NodeList = node.SelectSingleNode("child::*");
                if (NodeList.ChildNodes.Count > 0)
                    foreach (XmlNode nodec in NodeList.SelectSingleNode("child::*").SelectNodes("child::*"))
                    {
                        #region 表
                        xpathc = "//Table[@Name='" + nodec.Attributes["TableName"].Value + "']";
                        table = AddTable(bo, xml, xpathc, false);
                        if (table == null) return false;
                        #endregion
                        #region 字段
                        foreach (XmlNode nodefield in xml.SelectSingleNode(xpathc).SelectNodes("child::*"))
                        {
                            if (AddFeild(table, nodefield) == false)
                                return false;
                        }
                        #endregion
                    }
            }
            #endregion
            _BO = bo;
            #endregion
            #region 数据有效值
            IDictionary<string, IValidDataType> DicDataType = new Dictionary<string, IValidDataType>();
            IValidDataType DataType;
            IValidValue validValue;
            xpath = "//ValidDataType";
            foreach (XmlNode node in xml.SelectNodes(xpath))
            {
                var tempName = node.Attributes["name"].Value;
                var flag = false;
                if (DicDataType.ContainsKey(tempName))
                    flag = true;
                else
                    flag = false;
                if (flag)
                    DataType = DicDataType[tempName];
                else
                    DataType = new ValidDataType();
                DataType.DataTypeName = tempName;
                foreach (XmlNode nodec in node.SelectNodes("descendant::*"))
                {
                    if (DataType.lines.Contains(nodec.Attributes["Name"].Value))
                        continue;
                    validValue = DataType.lines.New();
                    validValue.ValidName = nodec.Attributes["Name"].Value;
                    validValue.ValidValue = nodec.Attributes["value"].Value;
                    validValue.ValidDescription = nodec.Attributes["Description"].Value;
                }
                if (flag == false)
                    DicDataType.Add(DataType.DataTypeName, DataType);
            }
            _DicValidDataType = DicDataType;
            #endregion
            return true;
        }

        public IBusinessObject BO
        {
            get
            {
                return _BO;
            }
        }
        public IDictionary<string, IValidDataType> DicValidDataType
        {
            get
            {
                return _DicValidDataType;
            }
        }

        //private void CreateInterface(string NameSpacePath, string Path, ITable table)
        //{
        //    string Note = string.Empty;
        //    //模板内容
        //    Note = File.OpenText(Path + "Interface.txt").ReadToEnd();
        //    #region 固定值
        //    //命名空间
        //    Note = Note.Replace("%Namespace%", _BO.NameSpace);
        //    //接口描述
        //    Note = Note.Replace("%InterfaceDescription%", table.Description);
        //    //接口名称
        //    Note = Note.Replace("%InterfaceName%", "I" + table.ClassName);
        //    //业务类型
        //    Note = Note.Replace("%BusinessObjectType%", "I" + table.Type.ToString());
        //    #endregion
        //    #region 属性值
        //    Regex re = new Regex(@"<\$Property\$>(.*)<\/\$Property\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
        //    string TemplateString = re.Matches(Note)[0].Value;
        //    string PropertiesString = TemplateString;
        //    TemplateString = TemplateString.Replace("<$Property$>", "");
        //    TemplateString = TemplateString.Replace("</$Property$>", "");
        //    string Properties = string.Empty;
        //    foreach (var field in table.Lines)
        //    {
        //        Properties += TemplateString
        //            .Replace("%PropertyDescription%", field.Description)
        //            .Replace("%PropertyType%", BusinessPlatform.Common.ConvertEx.ToSystemType(ConvertEx.ToSystemType(field.DbType)).ToString())
        //            .Replace("%PropertyName%", field.PropertyName);
        //    }
        //    Note = Note.Replace(PropertiesString, Properties);
        //    #endregion
        //    #region  属性中的集合类型
        //    if (_BO.Lines.Count > 0 && table.IsPrimary)
        //    {
        //        re = new Regex(@"<\$Collection\$>(.*)<\/\$Collection\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
        //        TemplateString = re.Matches(Note)[0].Value;
        //        PropertiesString = TemplateString;
        //        TemplateString = TemplateString.Replace("<$Collection$>", "");
        //        TemplateString = TemplateString.Replace("</$Collection$>", "");
        //        Properties = string.Empty;
        //        foreach (var item in _BO.Lines.GetChildTable())
        //        {
        //            //集合类型
        //            Properties += TemplateString
        //                .Replace("%CollectionDescription%", item.Description)
        //                .Replace("%CollectionType%", "I" + item.ClassName + "s")
        //                .Replace("%CollectionName%", item.ClassName + "s");
        //        }
        //        Note = Note.Replace(PropertiesString, Properties);
        //    }
        //    else
        //    {
        //        re = new Regex(@"<\$Collection\$>(.*)<\/\$Collection\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
        //        TemplateString = re.Matches(Note)[0].Value;
        //        Note = Note.Replace(TemplateString, "");
        //    }
        //    #endregion
        //    var sw = File.CreateText(NameSpacePath + "\\I" + table.ClassName + ".cs");
        //    sw.Write(Note);
        //    sw.Flush();
        //    sw.Close();
        //    sw.Dispose();
        //}
        //private void CreateCollectionInterface(string NameSpacePath, string Path, ITable table)
        //{
        //    string Note = string.Empty;
        //    //模板内容
        //    Note = File.OpenText(Path + "InterfaceLines.txt").ReadToEnd();
        //    //命名窗体
        //    Note = Note.Replace("%Namespace%", _BO.NameSpace);
        //    //接口描述
        //    Note = Note.Replace("%InterfaceDescription%", table.Description + "集合");
        //    //接口名称
        //    Note = Note.Replace("%InterfaceName%", "I" + table.ClassName + "s");
        //    //接口的父类型
        //    Note = Note.Replace("%ParentInterfaceName%", "I" + _BO.Lines.GetPrimaryTable().ClassName);
        //    //接口文件的子类型
        //    Note = Note.Replace("%ChildInterfaceName%", "I" + table.ClassName);
        //    var sw = File.CreateText(NameSpacePath + "\\I" + table.ClassName + "s.cs");
        //    sw.Write(Note);
        //    sw.Flush();
        //    sw.Close();
        //    sw.Dispose();
        //}
        //private void CreateClass(string NameSpacePath, string Path, ITable table)
        //{
        //    string Note = string.Empty;
        //    //模板内容
        //    Note = File.OpenText(Path + "Class.txt").ReadToEnd();
        //    #region 固定值
        //    //命名空间
        //    Note = Note.Replace("%Namespace%", _BO.NameSpace);
        //    //类描述
        //    Note = Note.Replace("%ClassDescription%", table.Description);
        //    //类名称
        //    Note = Note.Replace("%ClassName%", table.ClassName);
        //    //接口
        //    Note = Note.Replace("%InterfaceName%", "I" + table.ClassName);
        //    //数据表描述
        //    Note = Note.Replace("%TableDescription%", table.Description);
        //    //数据表
        //    Note = Note.Replace("%TableName%", table.Name);
        //    #endregion
        //    #region 属性值
        //    Regex re = new Regex(@"<\$Property\$>(.*)<\/\$Property\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
        //    string TemplateString = re.Matches(Note)[0].Value;
        //    string PropertiesString = TemplateString;
        //    TemplateString = TemplateString.Replace("<$Property$>", "");
        //    TemplateString = TemplateString.Replace("</$Property$>", "");
        //    string Properties = string.Empty;
        //    foreach (var field in table.Lines)
        //    {
        //        Properties += TemplateString
        //            .Replace("%PropertyDescription%", field.Description)//属性描述
        //            .Replace("%PropertyType%", BusinessPlatform.Common.ConvertEx.ToSystemType(ConvertEx.ToSystemType(field.DbType)).ToString())//属性类型
        //            .Replace("%PropertyName%", field.PropertyName)//属性名称
        //            .Replace("%FieldName%", field.Name)//字段名称
        //            .Replace("%DbType%", BusinessPlatform.Common.ConvertEx.ToSystemType(ConvertEx.ToSystemType(field.DbType)).ToString())//字段类型
        //            .Replace("%IsPrimary%", field.IsPrimaryKey == true ? ", IsPrimary = true" : "")//主键
        //            .Replace("%IsUnionKey%", field.IsUnionKey == true ? ", IsUnionKey = true" : "")//联合主键
        //            ;
        //    }
        //    Note = Note.Replace(PropertiesString, Properties);
        //    #endregion
        //    #region  属性中的集合类型
        //    if (_BO.Lines.Count > 0 && table.IsPrimary)
        //    {
        //        re = new Regex(@"<\$Collection\$>(.*)<\/\$Collection\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
        //        TemplateString = re.Matches(Note)[0].Value;
        //        PropertiesString = TemplateString;
        //        TemplateString = TemplateString.Replace("<$Collection$>", "");
        //        TemplateString = TemplateString.Replace("</$Collection$>", "");
        //        Properties = string.Empty;
        //        foreach (var item in _BO.Lines.GetChildTable())
        //        {
        //            //集合类型
        //            Properties += TemplateString
        //                .Replace("%CollectionDescription%", item.Description)
        //                .Replace("%ChildInterface%", "I" + item.ClassName + "s")
        //                .Replace("%ChildVariablePrivate%", "_" + item.ClassName + "s")
        //                .Replace("%ChildVariablePublic%", item.ClassName + "s")
        //                ;
        //        }
        //        Note = Note.Replace(PropertiesString, Properties);
        //    }
        //    else
        //    {
        //        re = new Regex(@"<\$Collection\$>(.*)<\/\$Collection\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
        //        TemplateString = re.Matches(Note)[0].Value;
        //        Note = Note.Replace(TemplateString, "");
        //    }
        //    #endregion
        //    #region 构造函数
        //    if (_BO.Lines.Count > 0 && table.IsPrimary)
        //    {
        //        re = new Regex(@"<\$Constrctor\$>(.*)<\/\$Constrctor\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
        //        TemplateString = re.Matches(Note)[0].Value;
        //        PropertiesString = TemplateString;
        //        TemplateString = TemplateString.Replace("<$Constrctor$>", "");
        //        TemplateString = TemplateString.Replace("</$Constrctor$>", "");
        //        Properties = string.Empty;
        //        foreach (var item in _BO.Lines.GetChildTable())
        //        {
        //            //集合类型
        //            Properties += TemplateString
        //                .Replace("%ChildVariablePrivate%", "_" + item.ClassName + "s")
        //                .Replace("%ChildClass%", item.ClassName + "s")
        //                .Replace("%ChildInterface%", "I" + item.ClassName + "s")
        //                .Replace("%ChildVariablePublic%", item.ClassName + "s")
        //                ;
        //        }
        //        Note = Note.Replace(PropertiesString, Properties);
        //    }
        //    else
        //    {
        //        re = new Regex(@"<\$Constrctor\$>(.*)<\/\$Constrctor\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
        //        TemplateString = re.Matches(Note)[0].Value;
        //        Note = Note.Replace(TemplateString, "");
        //    }
        //    #endregion
        //    var sw = File.CreateText(NameSpacePath + "\\" + table.ClassName + ".cs");
        //    sw.Write(Note);
        //    sw.Flush();
        //    sw.Close();
        //    sw.Dispose();
        //}
        //private void CreateCollectionClass(string NameSpacePath, string Path, ITable table)
        //{
        //    string Note = string.Empty;
        //    //模板内容
        //    Note = File.OpenText(Path + "ClassLines.txt").ReadToEnd();
        //    //命名窗体
        //    Note = Note.Replace("%Namespace%", _BO.NameSpace);
        //    //接口描述
        //    Note = Note.Replace("%ClassDescription%", table.Description + "集合");
        //    //接口名称
        //    Note = Note.Replace("%ClassName%", table.ClassName + "s");
        //    //接口的父类型
        //    Note = Note.Replace("%ParentInterfaceName%", "I" + _BO.Lines.GetPrimaryTable().ClassName);
        //    //继承的接口
        //    Note = Note.Replace("%InterfaceName%", "I" + table.ClassName + "s");
        //    //接口文件的子类型
        //    Note = Note.Replace("%ChildInterfaceName%", "I" + table.ClassName);
        //    //子类
        //    Note = Note.Replace("%ChildClassName%", table.ClassName);
        //    var sw = File.CreateText(NameSpacePath + "\\" + table.ClassName + "s.cs");
        //    sw.Write(Note);
        //    sw.Flush();
        //    sw.Close();
        //    sw.Dispose();
        //}
        //public void CreateCodeFiles(string BOPath)
        //{
        //    #region 创建对象的文件夹
        //    var NameSpacePath = BOPath + "\\" + _BO.NameSpace;
        //    Directory.CreateDirectory(NameSpacePath);
        //    #endregion
        //    var TempPath = System.Windows.Forms.Application.StartupPath + "\\Template\\CodeStructure\\";
        //    #region 创建Models文件
        //    foreach (var table in _BO.Lines)
        //    {
        //        //创建接口文件
        //        CreateInterface(NameSpacePath, TempPath + "Interface\\", table);
        //        //创建类型文件
        //        CreateClass(NameSpacePath, TempPath + "Class\\", table);
        //    }
        //    #region 集合接口
        //    foreach (var table in _BO.Lines.GetChildTable())
        //    {
        //        //创建接口文件
        //        CreateCollectionInterface(NameSpacePath, TempPath + "Interface\\", table);
        //        //创建类型文件
        //        CreateCollectionClass(NameSpacePath, TempPath + "Class\\", table);
        //    }
        //    #endregion
        //    #endregion
        //    #region 创建数据类型枚举

        //    #endregion
        //}
    }
}
